home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 15 / macformat_15.iso / Shareware Internet / Desarrolladores / gray image 2.1 / read_xwd.cc < prev    next >
Text File  |  1995-10-08  |  12KB  |  403 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *               Grayscale Image
  6.  *
  7.  *               Read an image from the X Window dump file
  8.  *
  9.  * $Id: read_xwd.cc,v 2.0 1995/03/09 15:23:17 oleg Exp oleg $
  10.  *
  11.  ************************************************************************
  12.  */
  13.  
  14. #include "image.h"
  15. #include "endian_io.h"
  16. #include "x11wd.h"
  17. #include <iostream.h>
  18.  
  19. /*
  20.  *------------------------------------------------------------------------
  21.  *            Create an image from the file
  22.  * This function attempt to determine the image file format by looking at
  23.  * the first two bytes of the file. They are
  24.  * 'Px' - for a Portable GrayMap
  25.  * 'MM' or 'II' - for a TIFF file
  26.  * otherwise, it _might_ be an X window dump.
  27.  * After the file format is guessed, the program calls an appropriate
  28.  * reader to actually load the file.
  29.  */
  30.  
  31. IMAGE::IMAGE(const char * file_name, const bool print_header_info)
  32. {
  33.   message("\nReading the file '%s' ",file_name);
  34.   EndianIn file(file_name);
  35.   assert( file.good() );
  36.  
  37.   char byte1 = file.peek();
  38.   if( byte1 == 'P' )
  39.     read_pgm(file,print_header_info);
  40.   else if( byte1 == 'M' || byte1 == 'I' )
  41.     read_tiff(file,print_header_info);
  42.   else
  43.     read_xwd(file,print_header_info);
  44. }
  45.  
  46. /*
  47.  *------------------------------------------------------------------------
  48.  *               Class XWDump
  49.  *     designed to contain the control info about the image
  50.  *        as defined in the X Window Dump file 
  51.  */
  52.  
  53. class XWDump            // All the info pertaining to the XWD file
  54.    : public X11WDFileHeader, public EndianIn
  55. {
  56. public:
  57.   char * win_name;                  // Name of the image in the file
  58.  
  59.   XWDump(EndianIn& file);            // Constructor
  60.   void info(void) const;            // Dump the header information
  61.  
  62.   void read_in_pixel_map(IMAGE& image);    // Reading the pixmap into image
  63. };
  64.  
  65. /*
  66.  *------------------------------------------------------------------------
  67.  *            Construct the XWDump
  68.  *       by reading the header of the X Window dump file
  69.  */
  70.  
  71. XWDump::XWDump(EndianIn& file) : EndianIn(file)
  72. {
  73.  
  74.   streampos beg_of_file = EndianIn::tellg();    // Remember the curr position
  75.   set_bigendian();        // Try reading a magic byte in one order
  76.   header_size = read_long("Reading the header_size");
  77.   file_version = read_long("Reading the XWD file version");
  78.  
  79.   if( file_version != X11WD_FILE_VERSION )
  80.   {
  81.     set_littlendian();        // Try now another byte order
  82.     EndianIn::seekg(beg_of_file);
  83.     header_size = read_long("Reading the header_size");
  84.     file_version = read_long("Reading the XWD file version");
  85.   }
  86.  
  87.   assure( file_version == X11WD_FILE_VERSION,
  88.      "I have tried different byte orders but failed to read\nthe XWD "
  89.      "file version correctly" );
  90.   assure( header_size >= sizeof(X11WDFileHeader),"XWD header is too small" );
  91.  
  92.                   // Read the rest of the header
  93.   pixmap_format    = read_long("Reading the pixmap_format");
  94.   pixmap_depth     = read_long("Reading the pixmap_depth");
  95.   pixmap_width     = read_long("Reading the pixmap_width");
  96.   pixmap_height    = read_long("Reading the pixmap_height");
  97.   xoffset          = read_long("Reading the xoffset");
  98.   xbyte_order      = read_long("Reading the byte_order");
  99.   bitmap_unit      = read_long("Reading the bitmap_unit");
  100.   bitmap_bit_order = read_long("Reading the bitmap_bit_order");
  101.   bitmap_pad       = read_long("Reading the bitmap_pad");
  102.   bits_per_pixel   = read_long("Reading the bits_per_pixel");
  103.   bytes_per_line   = read_long("Reading the bytes_per_line");
  104.   visual_class     = read_long("Reading the visual_class");
  105.   red_mask         = read_long("Reading the red_mask");
  106.   green_mask       = read_long("Reading the green_mask");
  107.   blue_mask        = read_long("Reading the blue_mask");
  108.   bits_per_rgb     = read_long("Reading the bits_per_rgb");
  109.   colormap_entries = read_long("Reading the colormap_entries");
  110.   ncolors          = read_long("Reading the ncolors");
  111.   window_width     = read_long("Reading the window_width");
  112.   window_height    = read_long("Reading the window_height");
  113.   window_x         = read_long("Reading the window_x");
  114.   window_y         = read_long("Reading the window_y");
  115.   window_bdrwidth  = read_long("Reading the window_bdrwidth");
  116.  
  117.                       // Read the window name
  118.   register int len = header_size - sizeof(X11WDFileHeader);
  119.   win_name = new char[len];
  120.   if( !EndianIn::read(win_name, len) )
  121.     error("Error reading the window name");
  122.  
  123.   if( ncolors > 0 )            // Skip the Xcolors
  124.     EndianIn::seekg(ncolors*sizeof(X11XColor),ios::cur);
  125. }
  126.  
  127. /*
  128.  *------------------------------------------------------------------------
  129.  *    Print out all the control information pertaining to the
  130.  *             X Window Image read
  131.  */
  132.  
  133. void XWDump::info(void) const
  134. {
  135.   cout << "\n\n=====>The following X Window dump has been read";
  136.   cout << "\nVersion:        " << file_version;
  137.   cout << "\nPixmap format:  ";
  138.   switch(pixmap_format)
  139.   {
  140.     case XYBitmap:
  141.          cout << "XYBitmap";
  142.          break;
  143.     case XYPixmap:
  144.          cout << "XYPixmap";
  145.          break;
  146.     case ZPixmap:
  147.          cout << "ZPixmap";
  148.          break;
  149.     default:
  150.      _error("Unknown pixel format: %d",pixmap_format);
  151.   }
  152.   cout << "\nPixmap depth:   " << pixmap_depth;
  153.   cout << "\nPixmap width:   " << pixmap_width;
  154.   cout << "\nPixmap height:  " << pixmap_height;
  155.   cout << "\nBitmap x offs:  " << xoffset;
  156.   cout << "\nByte order:     " << ( xbyte_order == MSBFirst ?
  157.                     "MSBFirst" : "LSBFirst" );
  158.   cout << "\nBitmap unit:    " << bitmap_unit;
  159.   cout << "\nBitmap bitOrder:" << ( bitmap_bit_order == MSBFirst ?
  160.                   "MSBFirst" : "LSBFirst" );
  161.   cout << "\nScanline pad:   " << bitmap_pad;
  162.   cout << "\nBits per pixel: " << bits_per_pixel;
  163.   cout << "\nBytes per line: " << bytes_per_line;
  164.   cout << "\nVisual class:   ";
  165.   switch(visual_class)
  166.   {
  167.     case StaticGray:
  168.          cout << "StaticGray";
  169.          break;
  170.     case GrayScale:
  171.          cout << "GrayScale";
  172.          break;
  173.     case StaticColor:
  174.          cout << "StaticColor";
  175.          break;
  176.     case PseudoColor:
  177.          cout << "PseudoColor";
  178.          break;
  179.     case TrueColor:
  180.          cout << "TrueColor";
  181.          break;
  182.     case DirectColor:
  183.          cout << "DirectColor";
  184.          break;
  185.     default:
  186.      _error("Unknown visual class: %d",visual_class);
  187.   }
  188.  
  189.   cout << "\nZ red mask:     0x" << ::hex << red_mask;
  190.   cout << "\nZ green mask:   0x" << ::hex << green_mask;
  191.   cout << "\nZ blue mask:    0x" << ::hex << blue_mask << ::dec;
  192.   cout << "\nBits per rgb:   " << bits_per_rgb;
  193.   cout << "\nColormap items: " << colormap_entries;
  194.   cout << "\nNo. colors:     " << ncolors;
  195.   cout << "\nWindow width:   " << window_width;
  196.   cout << "\nWindow height:  " << window_height;
  197.   cout << "\nWindow left  X: " << window_x;
  198.   cout << "\nWindow upper Y: " << window_y;
  199.   cout << "\nWindow border:  " << window_bdrwidth;
  200.   cout << "\nWindow name:    " << win_name;
  201.  
  202.   cout << "\n-----End of X Window dump information" << endl;
  203. }
  204.  
  205. /*
  206.  *------------------------------------------------------------------------
  207.  *        Read the image pixmap and write it into the image
  208.  */
  209.  
  210.                 // Load image from a Gray scale pixelmap
  211.                 // of depth 8 (that is, pixel matrix
  212.                 // arranged row-by-row)
  213. class load_8bit_pixmap : public PixelPrimAction
  214. {
  215.   EndianIn& ins;
  216.   void operation(GRAY& pixel)
  217.     { pixel = ins.read_byte("Reading the pixel map"); }
  218. public:
  219.   load_8bit_pixmap(EndianIn& _ins) : ins(_ins)
  220.     { message("\nReading the gray scale pixel map of depth 8..."); }
  221. };
  222.  
  223.                 // Try to load arbitrary pixel map from the
  224.                 // XWD file, doing pixel unpacking (and
  225.                 // conversion from rgb to the grayscale)
  226.                 // if necessary
  227. class load_any_pixmap : public PixelAction
  228. {
  229.   const int pixel_mask;            // Parameters of the pixel map
  230.   const int bits_per_pixel;        // (cached from XWDump header)
  231.   const int bits_per_item;
  232.   const int bit_order;
  233.   bool convert_rgb;
  234.  
  235.   EndianIn& ins;
  236.   char * scanline;
  237.   char * scanline_end;
  238.                 // Used in pixel unpacking
  239.   char *cp;                // Current scanline ptr
  240.   long int bits_storage;
  241.   int bit_shift;
  242.   int remains_bit;
  243.  
  244.   void load_scanline(void);
  245.   void operation(GRAY& pixel);
  246. public:
  247.   load_any_pixmap(XWDump& header);
  248.   virtual ~load_any_pixmap(void)    { delete scanline; }
  249. };
  250.                 // Prepare for loading pixelmap, initialize
  251.                 // param cacje and bit cache
  252. load_any_pixmap::load_any_pixmap(XWDump& header)
  253.    : pixel_mask(( 1 << header.bits_per_pixel ) - 1),
  254.      bits_per_pixel( header.bits_per_pixel ),
  255.      bits_per_item( header.bitmap_unit ),
  256.      bit_order( header.bitmap_bit_order ),
  257.      convert_rgb( header.visual_class == TrueColor ||
  258.          header.visual_class == DirectColor ),
  259.      ins(header),
  260.      bits_storage(0), bit_shift(0), remains_bit(0)
  261. {
  262.   scanline = new char[header.bytes_per_line];
  263.   scanline_end = scanline + header.bytes_per_line;
  264.   cp = &scanline[0];    
  265.  
  266.   if( convert_rgb )
  267.     message("\nA colored image with direct RGB specification\n"
  268.         "is to be converted to gray scale\n");
  269. }
  270.  
  271. void load_any_pixmap::load_scanline(void)
  272. {
  273.   switch( bits_per_item )        // Read a scanline
  274.   {
  275.     case 8:
  276.     {
  277.       for(register char *p = (char *)scanline; p < (char*)scanline_end;)
  278.     *p++ = ins.read_byte("Reading the scanline");
  279.     }
  280.     break;
  281.  
  282.     case 16:
  283.     {
  284.       for(register short *p = (short *)scanline; p < (short*)scanline_end;)
  285.       *p++ = ins.read_short("Reading the scanline");
  286.     }
  287.     break;
  288.  
  289.     case 32:
  290.     {
  291.       for(register long *p = (long *)scanline; p < (long*)scanline_end;)
  292.     *p++ = ins.read_long("Reading the scanline");
  293.     }
  294.     break;
  295.  
  296.     default:
  297.       assure(0,"can't happen");
  298.   }
  299.  
  300.   assert( row == 0 || cp == scanline_end );
  301.   cp = &scanline[0];
  302.   bits_storage = 0;
  303.   bit_shift = 0;
  304.   remains_bit = 0;
  305. }
  306.  
  307.  
  308.                 // Load the current (row,col) pixel
  309. void load_any_pixmap::operation(GRAY& pixel)
  310. {
  311.   if( col == 0 )
  312.     load_scanline();
  313.  
  314.   if( remains_bit == 0 )
  315.   {
  316.     switch(bits_per_item)
  317.     {
  318.       case 8:
  319.       bits_storage = *cp;
  320.       break;
  321.  
  322.       case 16:
  323.       bits_storage = *((short int *)cp);
  324.       break;
  325.  
  326.       case 32:
  327.       bits_storage = *((long int *)cp);
  328.       break;
  329.     }
  330.     cp += bits_per_item/8;
  331.     remains_bit = bits_per_item;
  332.     bit_shift = ( bit_order == MSBFirst ? bits_per_item - bits_per_pixel :
  333.          0 );
  334.   }
  335.   assert( bit_shift >= 0 );
  336.   register unsigned int raw_pixel = ( bits_storage >> bit_shift ) & pixel_mask;
  337.   bit_shift += ( bit_order == MSBFirst ? - bits_per_pixel : 
  338.         bits_per_pixel );
  339.   remains_bit -= bits_per_pixel;
  340.   assure(remains_bit >= 0,"Something goes wrong with bits conversion");
  341.  
  342.   if(convert_rgb)
  343.     pixel = ((raw_pixel & 0xff0000) << (20-16)) +    /* Red part    */
  344.             ((raw_pixel & 0xff00) << (10-8)) +        /* Green part    */
  345.         ((raw_pixel & 0xff));            /* Blue part    */
  346.   else
  347.     pixel = raw_pixel;
  348. }
  349.  
  350.  
  351.                 // Analyse the header and figure out if
  352.                 // we can handle the XWdump we've read.
  353.                 // Then set out to read the pixelmap
  354.                 // using the best strategy
  355. void XWDump::read_in_pixel_map(IMAGE& image)
  356. {
  357.   const int bits_per_item = bitmap_unit;
  358.  
  359.   if( pixmap_depth > 24 )
  360.     _error("can't handle X11 pixmap_depth %d greater than 24",pixmap_depth);
  361.   if( bits_per_rgb > 24 )
  362.     _error("can't handle X11 bits_per_rgb > 24");
  363.   if( pixmap_format != ZPixmap && pixmap_depth != 1 )
  364.     _error("can't handle X11 pixmap_format %d with depth != 1",pixmap_format);
  365.   if( bits_per_item != 8 && bits_per_item != 16 && bits_per_item != 32 )
  366.     _error("X11 bitmap_unit (%d) is non-standard - can't handle",
  367.        bits_per_item);
  368.   if( bits_per_item == 8 && bits_per_pixel == 8 && 
  369.       visual_class != TrueColor && visual_class != DirectColor )
  370.     image.apply(load_8bit_pixmap(*this));
  371. #if 0
  372.   else if( bits_per_item == 8 && bits_per_pixel == 1 )
  373.     pixmap_type = PT_BlackWhite;
  374. #endif
  375.   else
  376.     image.apply(load_any_pixmap(*this));
  377. }
  378.  
  379. /*
  380.  *========================================================================
  381.  *             Root module - actual IMAGE constructor
  382.  */
  383.  
  384. void IMAGE::read_xwd(EndianIn& file, const bool print_header_info)
  385. {
  386.   message("Reading the X window dump image\n");
  387.   
  388.   XWDump xwdump(file);
  389.  
  390.   if( print_header_info )
  391.     xwdump.info();
  392.  
  393.   allocate(xwdump.pixmap_height,xwdump.pixmap_width,xwdump.bits_per_pixel);
  394.  
  395.   name = xwdump.win_name;
  396.  
  397.   xwdump.read_in_pixel_map(*this);
  398.  
  399.   message("\n%dx%dx%d image '%s' has been read\n",ncols,nrows,
  400.         bits_per_pixel,name);
  401. }
  402.  
  403.